#include "common.h"
#include "eeprom.h"
#include "log.h"

//如果日志等级大于LOG_DEBUG，则会打印该日志，反之不会。
#define LOG_LOCAL_LEVEL LOG_DEBUG
#define TAG  "AT24C256:"

/*******************************************************************************
 * file:eeprom.c
 * author:armwnid
 * data: 2020.5.1
 * brief:eeprom驱动程序,当前开发板选用的是ATMLH909,读写寄存器地址均为16bit,这个要特别注意
 *
 * ***************************************************************************/

/**
  * @brief  初始化eeprom的I2c GPIO
  * @param  None
  * @retval None
  */
void IIC_Init(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);     //使能GPIOA

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_14 | GPIO_Pin_13;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;           //输出模式
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;          //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       //50MHz
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;        //外部已经有上拉了，这里不需要了
    GPIO_Init(GPIOA, &GPIO_InitStructure);                  //初始化
    IIC_SCL_H;
    IIC_SDAOUT_H;// = 1;
}
/**
  * @brief  I2c 起始信号产生函数
  * @param  None
  * @retval None
  */
void IIC_Start(void)
{
    SDA_OUT();     //设置SDA为输出
    IIC_SDAOUT_H;
    IIC_SCL_H;
    delay_us(4);
    IIC_SDAOUT_L;
    delay_us(4);
    IIC_SCL_L;
}

/**
  * @brief  I2c 停止信号产生函数
  * @param  None
  * @retval None
  */
void IIC_Stop(void)
{
    SDA_OUT();    //设置SDA为输出
    IIC_SCL_L;
    IIC_SDAOUT_L;
    delay_us(4);
    IIC_SCL_H;
    delay_us(4);
    IIC_SDAOUT_H;
}


  /**
    * @brief  等待I2C应答信号
    * @param  None
    * @retval None
    */
u8 MCU_Wait_Ack(void)
{
    u8 WaitTime = 0;
    SDA_IN();      //设置SDA为输入
    IIC_SDAOUT_H;
    delay_us(1);
    IIC_SCL_H;
    delay_us(1);
    while(IIC_SDAIN) {
        WaitTime++;
        if(WaitTime>250) {
            IIC_Stop();
            LOGE("wait timeout");
            return 1;
        }
    }
    IIC_SCL_L;
    return 0;
}

/**
  * @brief  发送I2C应答信号，可以看到SDA被置低了。
  * @param  None
  * @retval None
  */
void MCU_Send_Ack(void)
{
    IIC_SCL_L;
    SDA_OUT();
    IIC_SDAOUT_L;
    delay_us(2);
    IIC_SCL_H;
    delay_us(2);
    IIC_SCL_L;
}

/**
  * @brief  不发送应答信号，可以看到SDA被置高了
  * @param  None
  * @retval None
  */
void MCU_NOAck(void)
{
    IIC_SCL_L;
    SDA_OUT();
    IIC_SDAOUT_H;
    delay_us(2);
    IIC_SCL_H;
    delay_us(2);
    IIC_SCL_L;
}	

/**
  * @brief  向I2C总线发送一个字节
  * @param  Senddata：要写入的数据(8bit)
  * @retval None
  */
void IIC_write_OneByte(u8 Senddata)
{
    u8 t;
    SDA_OUT();
    IIC_SCL_L;
    for(t = 0; t < 8; t++) {
        if ((Senddata & 0x80) >> 7) { //先发送高位
            IIC_SDAOUT_H;
        } else {
            IIC_SDAOUT_L;
        }
        Senddata <<= 1;
        delay_us(2);
        IIC_SCL_H;
        delay_us(2);
        IIC_SCL_L;
        delay_us(2);
    }
} 

/**
  * @brief  读取I2C总线一个字节
  * @param  ack：接收完数据后，是否向I2C发送一个应答信号
  * @retval None
  */
u8 IIC_Read_OneByte(u8 ack)
{
    u8 i, receivedata = 0;
    SDA_IN();       //记得设置为输入功能
    for(i = 0; i < 8; i++) {
        IIC_SCL_L;
        delay_us(2);
        IIC_SCL_H;
        receivedata <<= 1;
        if(IIC_SDAIN) receivedata++;
        delay_us(1);
    }
    if (!ack)
        MCU_NOAck();//不发送应答
    else
        MCU_Send_Ack(); //发送应答信号
    return receivedata;
}

/**
  * @brief  初始化ATMELH909
  * @param  None
  * @retval None
  */
void ATMELH909_Init(void)
{
    IIC_Init();
}

/**
  * @brief  ATMELH909读取一个字节
  * @param  ReadAddr 读取的地址(16bit)
  * @retval None
  */
u8 ATMELH909_ReadByte(u16 ReadAddr)
{
    u8 receivedata=0;

    IIC_Start();
    IIC_write_OneByte(0XA0);           //这里设备写地址为0XA0
    MCU_Wait_Ack();
    IIC_write_OneByte(ReadAddr >> 8);               //高8位
    MCU_Wait_Ack();
    IIC_write_OneByte((u8)ReadAddr & 0xFF);         //低8位
    MCU_Wait_Ack();
    IIC_Start();
    IIC_write_OneByte(0XA1);           //读地址为0XA1
    MCU_Wait_Ack();
    receivedata = IIC_Read_OneByte(0);
    IIC_Stop();

    return receivedata;
}

/**
  * @brief  向ATMELH909写入一个字节
  * @param  WriteAddr 数据写入的地址16bit)
  *         WriteData 写入的数据
  * @retval None
  */
void ATMELH909_WriteByte(u16 WriteAddr,u8 WriteData)
{
    IIC_Start();
    IIC_write_OneByte(0XA0);       //这里设备写地址为0XA0�
    MCU_Wait_Ack();
    IIC_write_OneByte((u8)(WriteAddr >> 8));  //高8位ַ
    MCU_Wait_Ack();
    IIC_write_OneByte((u8)(WriteAddr&0xff));  //低8位ַ
    MCU_Wait_Ack();
    IIC_write_OneByte(WriteData);
    MCU_Wait_Ack();
    IIC_Stop();
    delay_ms(10);
}

